package com.ray.test.actuator.result;

import com.ray.test.actuator.params.ParamsBuilder;
import com.ray.test.actuator.params.ParamsInitBuilder;
import com.ray.test.mock.MockConfig;
import com.ray.test.util.ClassInstanceUtil;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author bo shen
 * @Description: 结果构建
 * @Class: ResultBuilder
 * @Package com.ray.test.actuator.result
 * @date 2019/12/13 10:43
 * @company <p>杭州传化陆鲸科技有限公司</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@Slf4j
public class ResultBuilder implements Bulider<Object> {

    private static ResultBuilder instance = new ResultBuilder();

    public static ResultBuilder getInstance() {
        return instance;
    }

    @Override
    public Object bulider(Method method, Type type) {
        try {
            if (ParameterizedType.class.isAssignableFrom(type.getClass())) {
                Class<?> classType = (Class<?>) ((ParameterizedType) type).getRawType();
                Type pType = ((ParameterizedType) type).getActualTypeArguments()[0];
                if(classType == Class.class)return null;
                if (classType == Set.class) {
                    Set set = new HashSet();
                    set.add(ParamsInitBuilder.getInstance().bulider((Class<?>) pType, method, null));
                    return set;
                } else if (classType == List.class) {
                    List<Object> list = new ArrayList<>();
                    list.add(ParamsInitBuilder.getInstance().bulider((Class<?>) pType, method, null));
                    return list;
                } else {
                    Object value = ClassInstanceUtil.getObject(classType);
                    mockObjectValue(value, (ParameterizedType) type, method);
                    return value;
                }
            } else if (TypeVariable.class.isAssignableFrom(type.getClass())) {
                return null;
            } else if ((Class<?>) type != void.class) {
                return ParamsInitBuilder.getInstance().bulider((Class<?>) type, method, null);
            }
        } catch (Exception e) {
            log.info("对象模拟数据失败", e);
        }
        return null;
    }

    /***模拟对象数据**/
    private void mockObjectValue(Object value, ParameterizedType type, Method method) throws Exception {
        if (value == null) return;
        for (Field field : ((Class) (type.getRawType())).getDeclaredFields()) {
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }
            field.setAccessible(true);
            Type ftype = field.getGenericType();
            log.info("当前转换类型:{}", field.getType());
            // 如果不为空并且是泛型参数的类型
            if (ftype instanceof TypeVariable) {
                Type pType = type.getActualTypeArguments()[0];
                if (pType instanceof ParameterizedType) {
                    ParameterizedType cpType = (ParameterizedType) pType;
                    if (List.class.isAssignableFrom((Class<?>) cpType.getRawType())) {
                        List<Object> list = new ArrayList<>();
                        for (int i = 0; i < MockConfig.getListSize(method); i++) {
                            list.add(ParamsInitBuilder.getInstance().bulider((Class<?>) cpType.getActualTypeArguments()[0], method, null));
                        }
                        field.set(value, list);
                    } else if (Set.class.isAssignableFrom((Class<?>) cpType.getRawType())) {
                        Set<Object> set = new HashSet<>();
                        for (int i = 0; i < MockConfig.getListSize(method); i++) {
                            set.add(ParamsInitBuilder.getInstance().bulider((Class<?>) cpType.getActualTypeArguments()[0], method, null));
                        }
                        field.set(value, set);
                    }
                } else {
                    field.set(value, ParamsInitBuilder.getInstance().bulider((Class<?>) pType, method, null));
                }
            } else {
                field.set(value, ParamsInitBuilder.getInstance().bulider(field.getType(), method, null));
            }
        }
    }


}
